package redis.inaction.ratelimiter.filter.ratelimit;

import lombok.extern.slf4j.Slf4j;

import javax.annotation.PostConstruct;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
public class TokenBucketRateLimiter {
    private static final String QUEUE_ITEM = "x";
    private final ArrayBlockingQueue<String> queue;

    private final int generateTokenNumEverySecond;
    private final Executor executor = Executors.newSingleThreadExecutor();
    private volatile boolean running = true;

    public TokenBucketRateLimiter(int limit, int periodInSecond, int generateTokenNumEverySecond) {
        this.queue = new ArrayBlockingQueue<>(limit);
        this.generateTokenNumEverySecond = generateTokenNumEverySecond;
    }

    @PostConstruct
    public void init(){
        //初始状态加满队列，表示当前可以处理这么多请求
       for(;;){
           if(!queue.offer(QUEUE_ITEM)){
               break;
           }
       }
       executor.execute(this::generateToken);
    }

    public boolean isAllow(){
        return queue.poll() != null;
    }

    private void generateToken(){
        while(running){
            for(int i = 0; i < generateTokenNumEverySecond; i++){
                if(!queue.offer(QUEUE_ITEM)){
                    break;
                }
            }
            sleepOneSecond();
        }
    }

    private void sleepOneSecond(){
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            log.warn("Interrupted");
        }
    }

}
